package com.wang.dmp.utils

import java.io.UnsupportedEncodingException
import java.net.URLEncoder
import java.security.NoSuchAlgorithmException
import java.util

import com.google.gson.{Gson, JsonObject, JsonParser}
import org.apache.commons.httpclient.HttpClient
import org.apache.commons.httpclient.methods.GetMethod
import org.apache.commons.lang3.StringUtils

import scala.collection.mutable

/**
 * 请求百度的LBS 解析经纬度的商圈信息
 * sn=068e2ffad88918200b68dd3828afdd34
 * http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=yourak&sn=7de5a22212ffaa9e326444c75a58f9a0
 * http://api.map.baidu.com/geocoding/v3/?address=北京市海淀区上地十街10号&output=json&ak=您的ak&callback=showLocation //GET请求
 */
object BaiDuLBSHandler {

  @throws[UnsupportedEncodingException]
  @throws[NoSuchAlgorithmException]
  def main(args: Array[String]): Unit = {


    println(paresBusinessTagBy("", ""))


  }


  /**
   * 对外提供的解析经纬度的商圈信息的方法
   *
   * @param lng 精度
   * @param lat 维度
   */

  def paresBusinessTagBy(lng: String, lat: String) = {

    var business: String = ""

    val requestParam = requestParams(lng, lat)
    //URL地址
    val requestURL = ConfigHandler.lbsDomain + requestParam

    //模拟http  浏览器客户端发送请求  get 请求
    val httpClient = new HttpClient()
    val getMethod = new GetMethod(requestURL)
    val statusCode = httpClient.executeMethod(getMethod)
    println(statusCode) //请求成功
    println(requestURL)
    if (statusCode == 200) {
      //返回响应的内容 json 但是前面有一些内容不对 判断是否是合法的json
      val response = getMethod.getResponseBodyAsString

      var str = response.replaceAll("renderReverse&&renderReverse\\(", "")
      if (!response.startsWith("{")) {
        str = str.substring(0, str.length - 1)
      }


      //解析json字符串 取出business节点的数据 取出business 商业标签
      val returnData = new JsonParser().parse(str).getAsJsonObject
      //json中服务器状态码 是否正常处理请求 ststus=0
      val status = returnData.get("status").getAsInt
      //判断
      if (status == 0) {
        val resultObject = returnData.getAsJsonObject("result")
        business = resultObject.get("business").getAsString
        //判断business是否为空，空的话解析坐标附近的信息"pois" :[{"addr":"",...
        if (StringUtils.isEmpty(business)) {
          val pois = resultObject.getAsJsonArray("pois")
          var tagSet = Set[String]()
          for (i <- 0 until pois.size()) {
            val elemObject: JsonObject = pois.get(i).getAsJsonObject
            val tag = elemObject.get("tag").getAsString
            if (StringUtils.isNotEmpty(tag)) tagSet += tag

          }
          business = tagSet.mkString(";")

        }

      }

    }

    business
    println(business)
  }


  private def requestParams(lng: String, lat: String) = {
    // 计算sn跟参数对出现顺序有关，get请求请使用LinkedHashMap保存<key,value>，该方法根据key的插入顺序排序；post请使用TreeMap保存<key,value>，该方法会自动将key按照字母a-z顺序排序。所以get请求可自定义参数顺序（sn参数必须在最后）发送请求，但是post请求必须按照字母a-z顺序填充body（sn参数必须在最后）。以get请求为例：http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=yourak，paramsMap中先放入address，再放output，然后放ak，放入顺序必须跟get请求中对应参数的出现顺序保持一致。
    val paramsMap = new util.LinkedHashMap[String, String]()
    paramsMap.put("callback", "renderReverse")
    paramsMap.put("address", "北京市海淀区上地十街10号")
    paramsMap.put("location", lat.concat(",").concat(lng))
    //paramsMap.put("location", "35.658651,139.745415")
    paramsMap.put("output", "json")
    paramsMap.put("pois", "1") //召回 附近一公里所有的信息
    paramsMap.put("ak", "ZZOA63nx6PGrMVGC4EnOHWeyoYsZGTn5")
    val paramsStr = toQueryString(paramsMap)

    //生成SN
    val wholeStr = new String("/geocoding/v3/?" + paramsStr + "Qfr6BahNfudm949o9FMydiGe1Gqi8z42")
    val tempStr = URLEncoder.encode(wholeStr, "UTF-8")
    val sn = MD5(tempStr)

    System.out.println(MD5(tempStr))

    paramsStr + "&sn=" + sn
  }


  // 对Map内所有value作utf8编码，拼接返回结果
  @throws[UnsupportedEncodingException]
  private def toQueryString(data: util.LinkedHashMap[String, String]): String = {
    val queryString = new StringBuffer
    import scala.collection.JavaConversions._
    for (pair <- data.entrySet) {
      queryString.append(pair.getKey + "=")
      queryString.append(URLEncoder.encode(pair.getValue.asInstanceOf[String], "UTF-8") + "&")
    }
    if (queryString.length > 0) queryString.deleteCharAt(queryString.length - 1)
    queryString.toString
  }

  // 来自stackoverflow的MD5计算方法，调用了MessageDigest库函数，并把byte数组结果转换成16进制
  private def MD5(md5: String): String = {
    try {
      val md = java.security.MessageDigest.getInstance("MD5")
      val array = md.digest(md5.getBytes)
      val sb = new StringBuffer
      var i = 0
      while ( {
        i < array.length
      }) {
        sb.append(Integer.toHexString((array(i) & 0xFF) | 0x100).substring(1, 3))

        {
          i += 1;
          i
        }
      }
      return sb.toString
    } catch {
      case e: NoSuchAlgorithmException =>

    }
    null
  }

}
